<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>函数节流</title>
	</head>
	<body>
		<div style="height:2000px">
			<p>节流：使得一定时间内只触发一次函数</p>
			<p>节流函数不管事件触发有多频繁，都会保证在规定时间内一定会执行一次真正的事件处理函数</p>
			<p>
				函数节流的要点是，声明一个变量当标志位，记录当前代码是否在执行。
			 如果空闲，则可以正常触发方法执行。
			 如果代码正在执行，则取消这次方法执行，直接return
			</p>
		</div>
		<script>
			/*
				var canRun = true;
				document.getElementById("throttle").onscroll = function(){
						if(!canRun){
								// 判断是否已空闲，如果在执行中，则直接return
								return;
						}

						canRun = false;
						setTimeout(function(){
								console.log("函数节流");
								canRun = true;
						}, 300);
				};
			*/
		</script>
		<script>
			/**
			 * 时间戳实现
			 * 时间戳实现：当高频事件触发时，第一次应该会立即执行（给事件绑定函数与真正触发事件的间隔如果大于delay的话），而后再怎么频繁触发事件，也都是会每delay秒才执行一次。而当最后一次事件触发完毕后，事件也不会再被执行了
			 **/
			/* 
				let startTime = Date.now();
				let delay = 1000;
				window.onscroll  = function(){
					let currentTime = Date.now();
					
					if(currentTime-startTime >= delay){ 
						let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
						console.log('滚动条位置：' + scrollTop);
						startTime = Date.now();
					}
				}
			*/
			/**
			 * 定时器实现
			 * 定时器实现： 当触发事件的时候，我们设置一个定时器，再触发事件的时候，如果定时器存在，就不执行；直到delay秒后，定时器执行执行函数，清空定时器，这样就可以设置下个定时器
			 * 
			 * 第一次不会立即执行
			 **/
			/* 
				let delay = 1000;
				let timer;
				window.onscroll  = function(){
					
					if(!timer){
						timer = setTimeout(function(){
							let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
							console.log('滚动条位置：' + scrollTop);
							timer = null;
						}, delay);
					}
				}
			*/
		</script>
		<script>
			window.onscroll  = throttle(function(){
				let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
				console.log('滚动条位置：' + scrollTop);		
			},800);
			
			
			/** 封装函数节流 
			通过闭包来实现。首先在函数内定义一个变量timer，然后返回一个函数，我们知道由于在返回函数中包含对timer的引用，因此timer并不会立即被清除
			**/
			function throttle(fun, delay){
				let timer = null,
						startTime = Date.now();
						
				return function(){
					let now = Date.now(),
							args = arguments,
							that = this;
							
					clearTimeout(timer);
					
					if(now-startTime >= delay){  //能执行
						fun.apply(that, args);
						startTime = now;
					}else{  //不能执行
						timer = setTimeout(function(){
              fun.apply(that, args);
            },delay);
					}
				}
			}
			
			
			
		</script>
	</body>
</html>
